
#ifndef SIM_H
#define SIM_H

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <map>
#include <vector>
#include "Vec3f.h"
#include "MissileBody.h"
//#include "ClientGame.h"
//#include "ServerGame.h"
using namespace std;

typedef map<int, GravBody> bodyMap;
typedef map<int, MissileBody> missileMap;


/*============================================================================*/
class Sim {

	public:
		Sim(int pNumMoons, int pNumDebris);
		Sim();  //thinSim only!!
		void start();
		void update();
		
		GravBody* getOrbitalBody(int index);
		GravBody* getDebrisBody(int index);
		int getOrbitalBodyOrder(int index);
		int getNumOrbitalBodies();
		int getNumDebrisBodies();
		bodyMap* getOrbitalBodyMap();
		bodyMap* getDebrisBodyMap();
		missileMap* getMissileBodyMap();

		void createMissileBody(int id, Missile* mInfo, Vec3f loc, Vec3f dest);
		void eraseMissileBody(int missileID);

		float getTotalRad();
		
		////thinSim functions only!!
		bool addOrbitalBody(int ID, Vec3f loc, float rad, float mass);
		bool addDebrisBody(int ID, Vec3f loc, float rad, float mass);
		void updateOrbitalBody(int id, Vec3f* loc, Vec3f* force);
		void updateDebrisBody(int id, Vec3f* loc);
		void thinSimStart();
		bool isThinSimRdy();
		////

		//void setServerGame(ServerGame * psgame){ sgame = psgame;}
		//ServerGame * getServerGame(){return sgame;}
		//ClientGame * getClientGame(){return cgame;}
		//void setClientGame(ClientGame * pcgame){ cgame = pcgame; } 
		

	private:
		double G;
		int numBodies;
		int numDebris;

		bool isThin;
		bool thinRdy;

		bodyMap bodies;
		bodyMap::iterator bodiesIter;
		vector<int>bodyOrder;
		bodyMap debris;
		bodyMap::iterator debrisIter;
		missileMap missiles;
		missileMap::iterator missilesIter;


		long timeNow;
		long timePass;
		long timePrev;
		float timeDT;

		//the sum of all the radii
		float totalRad;

		void userInit();
		void thinSimUpdate();
		void fatSimUpdate();
		void sortBodies(int beg, int end);
		void swapBodies(int a, int b);

		bool isCollision(GravBody* a, GravBody* b, float distSqr);
		void handleMoonMoonCollision(GravBody* a, GravBody* b);
		void handleMoonPlanetCollision(GravBody* a, GravBody* b);
		void handleDebrisMoonCollision(GravBody* a, GravBody* b);
		void handleDebrisPlanetCollision(GravBody* a, GravBody* b);

		//ClientGame * cgame;
		//ServerGame * sgame;
};

class portIP{
public:
	int port;
	string ipAddress;

	portIP(){
		port = 0;
		ipAddress = "";
	};

	portIP(int a, string b){
		port = a;
		ipAddress = b;
	};
};

class portIPSim{
public:
	int port;
	string ipAddress;
	Sim* gameSim;
	
	portIPSim(){
		port = 0;
		ipAddress = "";
		gameSim = new Sim(10,100);
	};
	portIPSim(int a, string b, Sim* c){
		port = a;
		ipAddress = b;
		gameSim = c;
	};
};

#endif
